package com.yfjin.gl.filter;

import android.content.Context;
import android.opengl.GLES20;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

@Deprecated
abstract public class AbstractFilter2 {

    protected int mProgram;

    private int vPositionHandler;
    private int vTextureCoordHandler;
    private int fSampleYHandler;
    private int fSampleUHandler;
    private int fSampleVHandler;

    private int mTextureIdY;
    private int mTextureIdU;
    private int mTextureIdV;


//    private FloatBuffer mVertexBuffer;
//    private final float[] VERTEX = {
//            -1f, -1f,
//            1f, -1f,
//            -1f, 1f,
//            1f, 1f
//    };
//
//    private FloatBuffer mTextureBuffer;
//    private final float[] TEXTURE = {
//            0.0f, 0.0f,
//            1.0f, 0.0f,
//            0.0f, 1.0f,
//            1.0f, 1.0f
//    };


//    private ByteBuffer mBufferY;
//    private ByteBuffer mBufferU;
//    private ByteBuffer mBufferV;

    private ByteBuffer mBuffer;

    public AbstractFilter2(Context context, int vertexShaderId, int fragShaderId) {


        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glDisable(GLES20.GL_DEPTH_TEST);
        GLES20.glDisable(GLES20.GL_DITHER);
        GLES20.glDisable(GLES20.GL_STENCIL_TEST);
        GLES20.glDisable(GL10.GL_DITHER);


        String vertexShader = OpenGLUtils.readRawTextFile(context, vertexShaderId);
        String fragShader = OpenGLUtils.readRawTextFile(context, fragShaderId);
        //编译-》连接-》运行
        mProgram = OpenGLUtils.loadProgram(vertexShader, fragShader);

        vPositionHandler = GLES20.glGetAttribLocation(mProgram, "vPosition");
        vTextureCoordHandler = GLES20.glGetAttribLocation(mProgram, "vCoord");

        fSampleYHandler = GLES20.glGetUniformLocation(mProgram, "fSampleY");
        fSampleUHandler = GLES20.glGetUniformLocation(mProgram, "fSampleU");
        fSampleVHandler = GLES20.glGetUniformLocation(mProgram, "fSampleV");


        initData();
        initOpenGl();
    }


    private static final int FLOAT_SIZE_BYTES = 4;
    private static final int SHORT_SIZE_BYTES = 2;
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
    private final float[] TRIANFLE_VERTICES_DATA = {
            1, -1, 0, 1, 1,
            1, 1, 0, 1, 0,
            -1, 1, 0, 0, 0,
            -1, -1, 0, 0, 1
    };
    private final short[] INDICES_DATA = {
            0, 1, 2,
            2, 3, 0
    };
    private FloatBuffer mTriangleVertices;
    private ShortBuffer mIndices;

    private void initData() {
//        mVertexBuffer = ByteBuffer.allocateDirect(4 * 4 * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
//        mVertexBuffer.clear();
//        mVertexBuffer.put(VERTEX);
//
//        mTextureBuffer = ByteBuffer.allocateDirect(4 * 4 * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
//        mTextureBuffer.clear();
//        mTextureBuffer.put(TEXTURE);

        mTriangleVertices = ByteBuffer.allocateDirect(TRIANFLE_VERTICES_DATA.length
                * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTriangleVertices.put(TRIANFLE_VERTICES_DATA).position(0);


        mIndices = ByteBuffer.allocateDirect(INDICES_DATA.length
                * SHORT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asShortBuffer();
        mIndices.put(INDICES_DATA).position(0);


        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
        GLES20.glVertexAttribPointer(vPositionHandler, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
        GLES20.glEnableVertexAttribArray(vPositionHandler);
        GLES20.glVertexAttribPointer(vTextureCoordHandler, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
        GLES20.glEnableVertexAttribArray(vTextureCoordHandler);

    }


    private void initOpenGl() {

        int[] textureIds = new int[3];
        GLES20.glGenTextures(3, textureIds, 0);
        mTextureIdY = textureIds[0];
        mTextureIdU = textureIds[1];
        mTextureIdV = textureIds[2];

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIdY);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIdU);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIdV);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    }


    private byte[] u = null;
    private byte[] v = null;

    public void onDraw(byte[] y, byte[] uv, int width, int height) {


        if (u == null) {
            u = new byte[(uv.length + 1) / 2];
            v = new byte[(uv.length + 1) / 2];
        }
        for (int i = 0; i < uv.length / 2; i++) {
            u[i] = uv[i * 2];
            v[i] = uv[i * 2 + 1];
        }

        if (mBuffer == null) {
            mBuffer = ByteBuffer.allocateDirect(width * height * 3 / 2);
        }
        mBuffer.rewind();
        mBuffer.put(y);
        mBuffer.put(u);
        mBuffer.put(v);

//        if (mBufferY == null) {
//            mBufferY = ByteBuffer.allocateDirect(y.length);
//        }
//        if (mBufferU == null) {
//            mBufferU = ByteBuffer.allocateDirect(u.length);
//        }
//        if (mBufferV == null) {
//            mBufferV = ByteBuffer.allocateDirect(v.length);
//        }
//        mBufferY.rewind();
//        mBufferY.put(y);
//
//        mBufferU.rewind();
//        mBufferU.put(u);
//
//        mBufferV.rewind();
//        mBufferV.put(v);

        GLES20.glViewport(0, 0, width/2, height/2);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        GLES20.glUseProgram(mProgram);

        //upload Y plane data
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIdY);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE
                , width, height
                , 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE
                , mBuffer.position(0));
        GLES20.glUniform1i(fSampleYHandler, 0);

        //update U plane data
        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIdU);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE
                , width >> 1, height >> 1
                , 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE
                , mBuffer.position(width*height));
        GLES20.glUniform1i(fSampleUHandler, 1);

        //update V plane data
        GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIdV);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE
                , width >> 1, height >> 1
                , 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE
                , mBuffer.position(width*height+width*height/4));
        GLES20.glUniform1i(fSampleVHandler, 2);


//        mVertexBuffer.position(0);
//        //2=每个顶点的个数
//        GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 0, mVertexBuffer);
//        GLES20.glEnableVertexAttribArray(vPosition);
//
//        mTextureBuffer.position(0);
//        GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer);
//        GLES20.glEnableVertexAttribArray(vCoord);
//
//
//        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, INDICES_DATA.length, GLES20.GL_UNSIGNED_SHORT, mIndices);

    }

    protected abstract void beforeDraw();

    public void release() {
        GLES20.glDeleteProgram(mProgram);
    }
}
